package com.wanmait.baohan.config;



import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.wanmait.baohan.shiro.BaoHanRealm;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

@Configuration
public class ShiroConfig {


    //创建DefaultWebSessionManager类，并DI注入到IOC容器中
    @Bean
    public DefaultWebSessionManager mySessionManager(){
        DefaultWebSessionManager defaultSessionManager = new DefaultWebSessionManager();
        //将sessionIdUrlRewritingEnabled属性设置成false
        defaultSessionManager.setSessionIdUrlRewritingEnabled(false);
        return defaultSessionManager;
    }



    // 项目启动shiroFilter首先会被初始化,并且逐层传入SecurityManager，Realm，matcher
    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
        /*
        shiro中内置的过滤器
            anno 无需认证的就可以访问
            authc 必须认证才能访问
            user 必须拥有记住我功能才能使用
            prems 拥有对某个资源的权限才能访问
            roles 拥有某个角色权限才能访问
         */
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(manager);
        //设置登录请求
        bean.setLoginUrl("/login");
        //成功后页面
        bean.setSuccessUrl("/index");
        //无权限后的页面
        bean.setUnauthorizedUrl("/error");

        //创建过滤器集合  键值对:请求-过滤器(权限配置)
        LinkedHashMap<String, String> filterChainDefinitonMap = new LinkedHashMap<>();
        //static下的文件放行
        filterChainDefinitonMap.put("/layui/**", "anon");
        filterChainDefinitonMap.put("/image/**", "anon");
        filterChainDefinitonMap.put("/favicon.ico", "anon");
        filterChainDefinitonMap.put("/login", "anon");
        //html文件全部要登录才能进入
        filterChainDefinitonMap.put("/**","authc");
        //放入Shiro过滤器
        bean.setFilterChainDefinitionMap(filterChainDefinitonMap);
        return bean;
    }

    //创建shiro安全管理器
    @Bean("securityManager")
    public SecurityManager securityManager(DefaultWebSessionManager defaultWebSessionManager, @Qualifier("baoHanRealm") BaoHanRealm baoHanRealm, @Qualifier("ehCacheManager") EhCacheManager ehCacheManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联ehcache缓存
        securityManager.setCacheManager(ehCacheManager);
        //关联会话管理defaultWebSessionManager
        securityManager.setSessionManager(defaultWebSessionManager);
        //关联realm
        securityManager.setRealm(baoHanRealm);
        return securityManager;
    }

    @Bean("baoHanRealm")
    public BaoHanRealm baoHanRealm(CredentialsMatcher credentialsMatcher) {

        BaoHanRealm baoHanRealm = new BaoHanRealm();
        //信息放入缓存
        //dbRealm.setCacheManager(new MemoryConstrainedCacheManager());
        //baoHanRealm.setAuthenticationCacheName("authenticationCache");
        //baoHanRealm.setCredentialsMatcher(credentialsMatcher);
        return baoHanRealm;
    }

    //shiro集成EhCache,但是没有交给spring去管理缓存，如果spring也使用ehcache则会出错

//   @Bean
//    public EhCacheManager ehCacheManager(){
//        EhCacheManager cacheManager = new EhCacheManager();
//        cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
//        return cacheManager;
//    }

    @Bean("ehCacheManager")
    public EhCacheManager ehCacheManager(CacheManager cacheManager) {
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManager(cacheManager);
        return ehCacheManager;
    }

    //加密
    @Bean
    public CredentialsMatcher credentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("md5");
        credentialsMatcher.setHashIterations(2);
        //credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }


    //启用controller的权限注解
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {

        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(manager);
        return advisor;
    }

    // 开启代理 不开启的话权限注解不起作用
    //@RequiresPermissions("userInfo:test")使这个能够使用
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }

    //百里香标签使用shiro属性
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}
